package exam_serv

import (
	"strconv"
	"strings"
	"ubt-aio-service/app/mod/exam_mod"
	"ubt-aio-service/app/pkg/db"
	"ubt-aio-service/app/utils"
)

type exam struct{}

var ExamServ = exam{}

// Add 新增
func (s *exam) Add(req *exam_mod.ExamSaveReq) *utils.ResJson {
	// 去掉主键，改为自动赋值模式
	sqlStr := "INSERT INTO exam_info(exam_id, title, begin_time, end_time, score, exam_time, img_names, img_urls, remarks, states, add_time, upd_time) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, 1, EXTRACT(epoch FROM NOW()), EXTRACT(epoch FROM NOW()))"
	return db.CudData(sqlStr, req.ExamId, req.Title, req.BeginTime, req.EndTime, req.Score, req.ExamTime, req.ImgNames, req.ImgUrls, req.Remarks)
}

// Exists 判断是否重复
func (s *exam) Exists(req *exam_mod.ExamExtVo) bool {
	// 注意修改对应的变量值
	sqlStr := "SELECT exam_id FROM exam_info WHERE states=1 AND title=$1"
	param := make([]any, 0)
	param = append(param, req.Title)
	if req.ExamId != "" {
		sqlStr += " AND exam_id!=$2"
		param = append(param, req.ExamId)
	}
	if res := db.GetOne(sqlStr, param...); res.Code == utils.Succeed.Code {
		return true
	}
	return false
}

// Update 修改
func (s *exam) Update(req *exam_mod.ExamSaveReq) *utils.ResJson {
	// 注意最后的索引值修改，以及去掉不需要修改的值
	sqlStr := "UPDATE exam_info SET title=$1, begin_time=$2, end_time=$3, score=$4, exam_time=$5, img_names=$6, img_urls=$7, remarks=$8, upd_time=EXTRACT(epoch FROM NOW()) WHERE exam_id=$9"
	// 需要将第一个值放到最后
	return db.CudData(sqlStr, req.Title, req.BeginTime, req.EndTime, req.Score, req.ExamTime, req.ImgNames, req.ImgUrls, req.Remarks, req.ExamId)
}

// DelOptByExam 删除
func (s *exam) DelOptByExam(ch chan int, examId string) {
	sqlStr := "DELETE FROM exam_info_opt WHERE exam_id=$1"
	db.CudData(sqlStr, examId)
	<-ch
}

// AddOpts 新增答案选项
func (s *exam) AddOpts(ch chan int, list []*exam_mod.ExamOptReq) {
	var (
		param []any
		n     = 0
	)
	sqlStr := "INSERT INTO exam_info_opt(opt_id, exam_id, kind, nums, score, remarks, states, add_time, upd_time) VALUES "
	for _, req := range list {
		sqlStr += "($" + strconv.Itoa(n+1) + ", $" + strconv.Itoa(n+2) + ", $" + strconv.Itoa(n+3) + ", $" + strconv.Itoa(n+4) + ", $" + strconv.Itoa(n+5) + ", $" + strconv.Itoa(n+6) + ", 1, EXTRACT(epoch FROM NOW()), EXTRACT(epoch FROM NOW())),"
		param = append(param, req.OptId)
		param = append(param, req.ExamId)
		param = append(param, req.Kind)
		param = append(param, req.Nums)
		param = append(param, req.Score)
		param = append(param, req.Remarks)
		n += 6
	}
	sqlStr = sqlStr[:len(sqlStr)-1]
	db.CudData(sqlStr, param...)
	<-ch
}

// Process 处理
func (s *exam) Process(req *exam_mod.ExamProcReq) *utils.ResJson {
	sqlStr := "UPDATE exam_info SET states=$1, upd_time=EXTRACT(epoch FROM NOW()) WHERE exam_id=$2"
	return db.CudData(sqlStr, req.States, req.ExamId)
}

// ProcOptsByExam 处理
func (s *exam) ProcOptsByExam(ch chan int, req *exam_mod.ExamProcReq) {
	sqlStr := "UPDATE exam_info_opt SET states=$1 WHERE exam_id=$2"
	db.CudData(sqlStr, req.States, req.ExamId)
	<-ch
}

// One 获取详情
func (s *exam) One(examId string) *utils.ResJson {
	sqlStr := "SELECT a.exam_id, a.title, a.begin_time, a.end_time, a.score, a.exam_time, a.img_names, a.img_urls, a.remarks, a.states, a.add_time, a.upd_time FROM exam_info a WHERE a.exam_id=$1"
	return db.GetOne(sqlStr, examId)
}

// List 获取配置列表
func (s *exam) List(examId string) *utils.ResJson {
	sqlStr := "SELECT a.opt_id, a.exam_id, a.kind, a.nums, a.score, a.remarks FROM exam_info_opt a WHERE a.states=1 AND a.exam_id=$1 ORDER BY a.kind"
	return db.GetAll(sqlStr, examId)
}

// Count 获取数量
func (s *exam) Count(req *exam_mod.ExamPageReq) *utils.ResJson {
	sqlStr := "SELECT COUNT(1) AS nums FROM exam_info WHERE states!=2"
	param := make([]any, 0)
	var n = 0
	if req.Keywords != "" {
		sqlStr += " AND ("
		nameArr := strings.Split(req.Keywords, " ")
		for _, name := range nameArr {
			sqlStr += "title LIKE '%'||$" + strconv.Itoa(n+1) + "||'%' OR "
			param = append(param, name)
			n += 1
		}
		sqlStr = sqlStr[:len(sqlStr)-4]
		sqlStr += ")"
	}
	if res := db.GetOne(sqlStr, param...); res.Code == utils.Succeed.Code && res.Data.(map[string]any)["nums"].(int64) > 0 {
		return res
	}
	return utils.NoData
}

// Page 获取分页列表
func (s *exam) Page(req *exam_mod.ExamPageReq) *utils.ResJson {
	sqlStr := "SELECT a.exam_id, a.title, a.begin_time, a.end_time, a.score, a.exam_time, a.states, a.add_time " +
		"FROM exam_info a " +
		"WHERE a.states!=2"
	param := make([]any, 0)
	var n = 0
	if req.Keywords != "" {
		sqlStr += " AND ("
		nameArr := strings.Split(req.Keywords, " ")
		for _, name := range nameArr {
			sqlStr += "a.title LIKE '%'||$" + strconv.Itoa(n+1) + "||'%' OR "
			param = append(param, name)
			n += 1
		}
		sqlStr = sqlStr[:len(sqlStr)-4]
		sqlStr += ")"
	}
	sqlStr += " ORDER BY a.add_time DESC LIMIT $" + strconv.Itoa(n+1) + " OFFSET $" + strconv.Itoa(n+2)
	param = append(param, req.Limit)
	param = append(param, req.Offset)
	return db.GetAll(sqlStr, param...)
}

// Select 获取列表
func (s *exam) Select() *utils.ResJson {
	sqlStr := "SELECT exam_id AS sel_id, title AS sel_name FROM exam_info WHERE states=1"
	return db.GetAll(sqlStr)
}
